package com.netty.netty.high.demo5;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author 游政杰
 * @date 2022/1/13
 * 模拟 Redis client
 */
public class RedisSender {

    //true为继续循环，false是退出循环
  private static ThreadLocal<Boolean> threadLocal=new ThreadLocal<Boolean>();
  private static final Logger log= LoggerFactory.getLogger(RedisSender.class);

  public static void main(String[] args) {

      //Netty“”客户端“”执行Redis命令
      NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
      try{

      new Bootstrap()
              .group(nioEventLoopGroup)
              .channel(NioSocketChannel.class)
              .handler(new ChannelInitializer<Channel>() {
                  @Override
                  protected void initChannel(Channel ch) throws Exception {

                      threadLocal.set(true); //默认是继续循环

                      ch.pipeline().addLast(new LoggingHandler());


                      ch.pipeline().addLast("handle1",new ChannelInboundHandlerAdapter(){

                          //连接成功之后调用
                          @Override
                          public void channelActive(ChannelHandlerContext ctx) throws Exception {

                              Scanner sc = new Scanner(System.in);
                              for (;;){
                                  if(!threadLocal.get()){
                                      System.out.println("退出成功");
                                      break;
                                  }
                                  printInfo();
                                  String sel = sc.next();
                                  switch (sel)
                                  {
                                      case "a":
                                          sc.nextLine(); //***上面会传下来字符，导致无法输入字符串，所以要加上这句，目的是吸收上面传下来的多余字符串
                                          System.out.println("请输入Redis命令[以单空格分隔]：");
                                          String redis_cmd = sc.nextLine();
                                          String decodeProtocol = decodeProtocol(redis_cmd);
                                          ByteBuf buffer = ctx.alloc().buffer(16);
                                          buffer.writeBytes(decodeProtocol.getBytes("utf-8"));
                                          ctx.writeAndFlush(buffer);
                                          buffer.clear();
                                          break;
                                      case "q":
                                          ch.close();
                                          ChannelFuture closeFuture = ch.closeFuture();
                                          closeFuture.addListener(new ChannelFutureListener() {
                                              @Override
                                              public void operationComplete(ChannelFuture future) throws Exception {
                                                  nioEventLoopGroup.shutdownGracefully();
                                                  threadLocal.set(false); //退出只需要设置为false即可
                                              }
                                          });
                                          break;
                                      default:
                                          System.out.println("无该选项");
                                          break;
                                  }
                              }


                          }
                      });
                  }
              }).connect("localhost",6379);
      }catch (Exception e){
          e.printStackTrace();
          nioEventLoopGroup.shutdownGracefully();
      }

  }

  private static void printInfo()
  {
    System.out.println("请输入以下字符选项：");
    System.out.println("输入a：执行Redis命令");
    System.out.println("输入q：退出");
  }


    /**
     * 协议解析
     * @param redis_cmd 命令
     * @return
     */
    //set myname abc
    //del key
    //get key
  private static synchronized String decodeProtocol(String redis_cmd){
      String delimiter1="*";
      String delimiter2="$";
      String delimiter3="\r\n";
      StringBuffer decodeCmd = new StringBuffer();//使用线程安全的StringBuffer
      List<String> cmd = Arrays.asList(redis_cmd.split(" "));
      decodeCmd.append(delimiter1+cmd.size()+delimiter3);
      cmd.forEach((e)->{

          decodeCmd.append(delimiter2+e.length()+delimiter3);
          decodeCmd.append(e+delimiter3);
      });

      return decodeCmd.toString();
  }

}
